package es.us.lsi.daw.servicios;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

import org.springframework.validation.BeanPropertyBindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.Validator;

import es.us.lsi.daw.dao.DAOAcceso;
import es.us.lsi.daw.enums.TipoValidacion;



public class Validar extends DAOAcceso implements Validator {
	
	private String nombreAtributo;
	
	public void validate(Object objeto,Errors errores){		
		
		List<Field> lstCampos = new ArrayList<Field>(); 
		for(Field f: objeto.getClass().getDeclaredFields())
			lstCampos.add(f);
		if(objeto.getClass().getSuperclass() != null){
			for(Field f: objeto.getClass().getSuperclass().getDeclaredFields())
				lstCampos.add(f);
		}		
		for(Field f: lstCampos){
			try {		
				List<TipoValidacion> lstValidaciones = TipoValidacion.stringToTipoValidacion(f.getAnnotations());
				Object valor = null;
				String campoError = "";
				if(lstValidaciones.size() > 0){									
					f.setAccessible(true);
					valor = f.get(objeto);
					if(!objeto.getClass().equals(((BeanPropertyBindingResult)errores).getTarget().getClass()))						
						campoError = nombreAtributo + "." + f.getName();
					else
						campoError = f.getName();
				}
				for(TipoValidacion tipo: lstValidaciones){						
					 switch (tipo.ordinal()) {
			            case 0://Requerido
			            	if(errores.getFieldErrorCount(campoError) == 0){				            	
			            		if(valor == null || (valor != null && !(valor instanceof List) && valor.getClass().equals(String.class) && valor.toString().isEmpty())){
				            		errores.rejectValue(campoError, "requerido." + f.getName(),f.getName() + " is required.");
				            	}else if(valor == null || (valor != null && valor instanceof List && ((List)valor).isEmpty())){
				            		errores.rejectValue(campoError, "requerido." + f.getName(),f.getName() + " is required.");
				            	}
			            	}
			            	break;
			            case 1://Email			            	
			            		String patronEmail = "^[\\w-_\\.+]*[\\w-_\\.]\\@([\\w]+\\.)+[\\w]+[\\w]$";
			            		if (errores.getFieldErrorCount(campoError) == 0 && valor !=null && !valor.toString().isEmpty() && !valor.toString().matches(patronEmail))
			            			errores.rejectValue(campoError, "incorrecto." + f.getName(), f.getName() + " is incorrect");
			            	break;	
			            case 2://Unico		            			            		
		            		if (errores.getFieldErrorCount(campoError) == 0 && this.daoComun.existe(objeto,valor,f.getName()) && valor != null && (valor.getClass().equals(String.class) && !valor.toString().isEmpty()))
		            			errores.rejectValue(campoError, "","The value of " + f.getName().substring(0,1).toUpperCase() + f.getName().substring(1) + " must be unique.");
		            	break;
			            case 3://NumericoEntero
			            	String numeros = "[0-9]*";
		            		if (errores.getFieldErrorCount(campoError) == 0 && valor !=null && !valor.toString().isEmpty() && !valor.toString().matches(numeros))
		            			errores.rejectValue(campoError, "","The value of " + f.getName().substring(0,1).toUpperCase() + f.getName().substring(1) + " must be a number.");
		            	break;
			            case 4://NumericoFloat
			            	String numerosFloat = "[0-9]*\\.[0-9]*";
		            		if (errores.getFieldErrorCount(campoError) == 0 && valor != null && !valor.toString().isEmpty() && !valor.toString().matches(numerosFloat))
		            			errores.rejectValue(campoError, "","The value of " + f.getName().substring(0,1).toUpperCase() + f.getName().substring(1) + " must be a number.");
		            	break;
			            case 5://Hora
			            	String hora = "(0[0-9]|1[0-9]|2[0-3]):[0-5][0-9]";
		            		if (errores.getFieldErrorCount(campoError) == 0 && valor !=null && !valor.toString().isEmpty() && !valor.toString().matches(hora))
		            			errores.rejectValue(campoError, "incorrecto.hora","The value of " + f.getName().substring(0,1).toUpperCase() + f.getName().substring(1) + " must follow the format HH:MM.");
		            	break;
			            case 6://Fecha
			            	String fecha = "([0-2][0-9]|30|31)/(0[0-9]|10|11|12)/([0-9][0-9][0-9][0-9])";
		            		if (errores.getFieldErrorCount(campoError) == 0 && valor !=null && !valor.toString().isEmpty() && !valor.toString().matches(fecha))
		            			errores.rejectValue(campoError, "incorrecto.fecha","The value of " + f.getName().substring(0,1).toUpperCase() + f.getName().substring(1) + " must follow the format dd/MM/yyyy.");
		            	break;
//			            case 8://Comparacion
//			            	Comparacion c = f.getAnnotation(Comparacion.class);
//			            	if(c != null){
//			            		String nombreCampo = "";
//			            		Object valorComparacion = null;
//			            		if(!c.valor().isEmpty()){
//									valorComparacion = c.valor();
//									nombreCampo = c.valor();
//								}else if(!c.atributo().isEmpty()){										
//									valorComparacion =  Util.obtenerValorCampo(c.atributo(),objeto);																		
//									nombreCampo = c.atributo();									
//								}
//				            	switch (c.tipo().toInt()) {
//									case 0://Mayor estricto
//										if(f.getType().equals(Date.class)){
//											Date fechaAux = (Date)valor;
//											Date fecha1 = new Date(fechaAux.getYear(),fechaAux.getMonth(),fechaAux.getDay(),0,0);
//										}else if(f.getType().equals(Calendar.class)){
//												valorComparacion = Util.formatearFecha(((Calendar)valorComparacion).getTime());
//												valor = Util.formatearFecha(((Calendar)valor).getTime());
//											
//										}else if(!(valor.toString().compareTo(valorComparacion.toString()) > 0))
//											errores.rejectValue(campoError,"comparacion.mayorEstricto." + f.getName(),f.getName() + " debe ser mayor que " + nombreCampo);																															
//										break;
//									case 1://Mayor o igual
//										if(!(valor.toString().compareTo(valorComparacion.toString()) >= 0))
//											errores.rejectValue(campoError,"comparacion.mayorIgual." + f.getName(),f.getName() + " debe ser mayor o igual que " + nombreCampo);										
//										break;
//									case 2://Menor estricto
//										if(!(valor.toString().compareTo(valorComparacion.toString()) < 0))
//											errores.rejectValue(campoError,"comparacion.menorEstricto." + f.getName(),f.getName() + " debe ser menor que " + nombreCampo);										
//										break;
//									case 3://Menor o igual
//										if(!(valor.toString().compareTo(valorComparacion.toString()) <= 0))
//											errores.rejectValue(campoError,"comparacion.menorIgual." + f.getName(),f.getName() + " debe ser menor o igual que " + nombreCampo);										
//										break;
//									case 4://Igual
//										if(!(valor.toString().compareTo(valorComparacion.toString()) == 0))
//											errores.rejectValue(campoError,"comparacion.igual." + f.getName(),f.getName() + " debe ser igual que " + nombreCampo);										
//										break;
//								}
//			            	}
//			            	break;
			        }					
				}
			} catch (IllegalArgumentException e) {				
				e.printStackTrace();
			} catch (Exception e) {				
				e.printStackTrace();
			}
		}	
		
		this.nombreAtributo = null;
	}

	public boolean supports(Class arg0) {		
		return false;
	}

	public void setNombreAtributo(String nombreAtributo) {
		this.nombreAtributo = nombreAtributo;
	}

	public String getNombreAtributo() {
		return nombreAtributo;
	}


}
